//package cn.code.service;
//
//import io.milvus.client.MilvusServiceClient;
//import io.milvus.grpc.DataType;
//import io.milvus.grpc.SearchResults;
//import io.milvus.param.*;
//import io.milvus.grpc.SearchResultData;
//import io.milvus.param.collection.CreateCollectionParam;
//import io.milvus.param.collection.DropCollectionParam;
//import io.milvus.param.collection.FieldType;
//import io.milvus.param.collection.HasCollectionParam;
//import io.milvus.param.dml.InsertParam;
//import io.milvus.param.dml.SearchParam;
//import io.milvus.param.index.CreateIndexParam;
//import io.milvus.param.MetricType;
//import io.milvus.param.IndexType;
//import io.milvus.response.SearchResultsWrapper;
//import jakarta.annotation.PostConstruct;
//import jakarta.annotation.PreDestroy;
//import org.springframework.beans.factory.annotation.Value;
//import org.springframework.stereotype.Service;
//
//import java.util.ArrayList;
//import java.util.List;
//
//@Service
//public class VectorDBService {
//
//    @Value("${spring.milvus.host}")
//    private String host;
//
//    @Value("${spring.milvus.port}")
//    private int port;
//
//    @Value("${spring.milvus.token}")
//    private String token;
//
//    @Value("${spring.milvus.collection-name}")
//    private String collectionName;
//
//    @Value("${app.vector-db.dimension}")
//    private int dimension;
//
//    // IVF_FLAT: 是桶索引，将数据集分成多个桶，每个桶包含相似的向量。
//    // FLAT: 是最简单的索引，将所有向量存储在索引中。
//    @Value("${app.vector-db.index-type}")
//    private String indexType;
//
//    // L2是：欧式距离，计算两个向量的欧式距离。
//    // IP是：内积，计算两个向量的内积。
//
//    @Value("${app.vector-db.metric-type}")
//    private String metricType;
//
//    private MilvusServiceClient milvusClient;
//
//    @PostConstruct
//    public void init() {
//        ConnectParam connectParam = ConnectParam.newBuilder()
//                .withHost(host)
//                .withPort(port)
//                .withToken(token)
//                .build();
//
//        milvusClient = new MilvusServiceClient(connectParam);
//        createCollectionIfNotExists();
//        createIndexIfNotExists();
//    }
//
//    @PreDestroy
//    public void cleanup() {
//        if (milvusClient != null) {
//            milvusClient.close();
//        }
//    }
//
//    /**
//     * 创建集合（如果不存在）
//     */
//    private void createCollectionIfNotExists() {
//        R<Boolean> resp = milvusClient.hasCollection(HasCollectionParam.newBuilder()
//                .withCollectionName(collectionName)
//                .build());
//
//        if (!resp.getData()) {
//            // 定义字段
//            FieldType idField = FieldType.newBuilder()
//                    .withName("id")
//                    .withDataType(DataType.Int64)
//                    .withPrimaryKey(true)
//                    .withAutoID(true)
//                    .build();
//
//            FieldType contentField = FieldType.newBuilder()
//                    .withName("content")
//                    .withDataType(DataType.VarChar)
//                    .withMaxLength(65535)
//                    .build();
//
//            FieldType vectorField = FieldType.newBuilder()
//                    .withName("vector")
//                    .withDataType(DataType.FloatVector)
//                    .withDimension(dimension)
//                    .build();
//
//            FieldType fileTypeField = FieldType.newBuilder()
//                    .withName("file_type")
//                    .withDataType(DataType.VarChar)
//                    .withMaxLength(50)
//                    .build();
//
//            FieldType fileNameField = FieldType.newBuilder()
//                    .withName("file_name")
//                    .withDataType(DataType.VarChar)
//                    .withMaxLength(255)
//                    .build();
//
//            // 创建集合
//            CreateCollectionParam createParam = CreateCollectionParam.newBuilder()
//                    .withCollectionName(collectionName)
//                    .withDescription("Document embeddings collection")
//                    .addFieldType(idField)
//                    .addFieldType(contentField)
//                    .addFieldType(vectorField)
//                    .addFieldType(fileTypeField)
//                    .addFieldType(fileNameField)
//                    .build();
//
//            milvusClient.createCollection(createParam);
//        }
//    }
//
//    /**
//     * 创建索引（如果不存在）
//     */
//    private void createIndexIfNotExists() {
//        CreateIndexParam createIndexParam = CreateIndexParam.newBuilder()
//                .withCollectionName(collectionName)
//                .withFieldName("vector")
//                .withIndexType(IndexType.valueOf(indexType))
//                .withMetricType(MetricType.valueOf(metricType))
//                .withExtraParam("{\"nlist\":1024}")
//                .build();
//
//        milvusClient.createIndex(createIndexParam);
//    }
//
//    /**
//     * 插入文档嵌入
//     */
//    public boolean insertDocument(String content, List<Float> vector, String fileType, String fileName) {
//        List<InsertParam.Field> fields = new ArrayList<>();
//        fields.add(new InsertParam.Field("content", List.of(content)));
//        fields.add(new InsertParam.Field("vector", List.of(vector)));
//        fields.add(new InsertParam.Field("file_type", List.of(fileType)));
//        fields.add(new InsertParam.Field("file_name", List.of(fileName)));
//
//        InsertParam insertParam = InsertParam.newBuilder()
//                .withCollectionName(collectionName)
//                .withFields(fields)
//                .build();
//
//        R<io.milvus.grpc.MutationResult> response = milvusClient.insert(insertParam);
//        return response.getStatus() == R.Status.Success.getCode();
//    }
//
//    /**
//     * 搜索相似文档
//     */
//    public List<SearchResult> searchSimilarDocuments(List<Float> queryVector, int topK) {
//        String searchParam = "";
//        List<List<Float>> searchVectors = List.of(queryVector);
//
//        SearchParam param = SearchParam.newBuilder()
//                .withCollectionName(collectionName)
//                .withMetricType(MetricType.valueOf(metricType))
//                .withOutFields(List.of("content", "file_type", "file_name"))
//                .withTopK(topK)
//                .withVectors(searchVectors)
//                .withVectorFieldName("vector")
//                .withExpr(searchParam)
//                .build();
//
//        R<SearchResults> response = milvusClient.search(param);
//        if (response.getStatus() != R.Status.Success.getCode()) {
//            return new ArrayList<>();
//        }
//        SearchResultsWrapper wrapper = new SearchResultsWrapper(response.getData());
//        List<SearchResult> results = new ArrayList<>();
//
//        for (int i = 0; i < topK; i++) {
//            SearchResultsWrapper.IDScore score = wrapper.getIDScore(0, i);
//            if (score != null) {
//                String content = wrapper.getFieldData("content", 0, i).toString();
//                String fileType = wrapper.getFieldData("file_type", 0, i).toString();
//                String fileName = wrapper.getFieldData("file_name", 0, i).toString();
//
//                results.add(new SearchResult(content, fileType, fileName, score.getScore()));
//            }
//        }
//
//        return results;
//    }
//
//    /**
//     * 删除集合
//     */
//    public boolean dropCollection() {
//        R<RpcStatus> response = milvusClient.dropCollection(DropCollectionParam.newBuilder()
//                .withCollectionName(collectionName)
//                .build());
//        return response.getStatus() == R.Status.Success.getCode();
//    }
//
//    /**
//     * 搜索结果类
//     */
//    public static class SearchResult {
//        private final String content;
//        private final String fileType;
//        private final String fileName;
//        private final float score;
//
//        public SearchResult(String content, String fileType, String fileName, float score) {
//            this.content = content;
//            this.fileType = fileType;
//            this.fileName = fileName;
//            this.score = score;
//        }
//
//        public String getContent() { return content; }
//        public String getFileType() { return fileType; }
//        public String getFileName() { return fileName; }
//        public float getScore() { return score; }
//    }
//}
